package com.xiyu.service.service.elder;

import com.xiyu.service.enums.infra.InfraBooleanStringEnum;
import com.xiyu.service.vo.elder.visit.VisitSingleGetOutput;
import com.xiyu.service.enums.elder.register.ElderVisitStatusEnum;
import com.xiyu.service.model.elder.register.ElderVisitDraft;
import com.xiyu.service.vo.elder.visit.VisitUpdateStatusInput;
import com.xiyu.service.vo.elder.visit.VisitUpdateInput;
import com.xiyu.service.vo.elder.visit.VisitCreateInput;
import com.xiyu.service.model.elder.register.ElderVisit;
import com.xiyu.service.repository.elder.register.ElderVisitRepository;
import com.xiyu.service.vo.elder.visit.VisitPageQueryOutput;
import com.xiyu.service.vo.elder.visit.VisitPageQueryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.elder.VisitConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.elder.VisitErrorCode.*;

/**
 * 来访登记 Service 实现类
 */
@Service
@Validated
public class VisitServiceImpl implements VisitService {

    @Resource
    private ElderVisitRepository elderVisitRepository;


    @Override
    public PageResult<VisitPageQueryOutput> pageQuery(VisitPageQueryInput inputVO) {
        Page<ElderVisit> pageElderVisit = elderVisitRepository.pageQuery(inputVO);
        List<VisitPageQueryOutput> listElderVisit = VisitConvert.INSTANCE.pageQueryOutputConvert(pageElderVisit.getRows());
        return new PageResult<>(listElderVisit, pageElderVisit.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(VisitCreateInput inputVO) {
        ElderVisit newElderVisit = VisitConvert.INSTANCE.createInputConvert(inputVO);
        newElderVisit = ElderVisitDraft.$.produce(newElderVisit, draft -> {
            if(inputVO.getVisitTime().isAfter(LocalDateTime.now())){
                draft.setStatus(ElderVisitStatusEnum.RESERVED.getValue()).setIsReserve(true).setReserveTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }else{
                draft.setStatus(ElderVisitStatusEnum.VISITED.getValue()).setIsReserve(false);
            }
        });
        newElderVisit = elderVisitRepository.insert(newElderVisit);
        return newElderVisit.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(VisitUpdateInput inputVO) {
        Optional<ElderVisit> optionalOldElderVisit = elderVisitRepository.findById(inputVO.getId());
        if(!optionalOldElderVisit.isPresent()){
            throw exception(ELDER_VISIT_NOT_EXIST);
        }
        ElderVisit updateElderVisit = VisitConvert.INSTANCE.updateInputConvert(inputVO);
        updateElderVisit = ElderVisitDraft.$.produce(updateElderVisit, draft -> {
            if(inputVO.getVisitTime().isAfter(LocalDateTime.now())){
                draft.setStatus(ElderVisitStatusEnum.RESERVED.getValue()).setIsReserve(true).setReserveTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }else{
                draft.setStatus(ElderVisitStatusEnum.VISITED.getValue()).setIsReserve(false).setReserveTime("");
            }
        });
        elderVisitRepository.update(updateElderVisit);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatus(VisitUpdateStatusInput inputVO) {
        Optional<ElderVisit> optionalElderVisit = elderVisitRepository.findById(inputVO.getId());
        if(!optionalElderVisit.isPresent()){
            throw exception(ELDER_VISIT_NOT_EXIST);
        }
        ElderVisit elderVisit = optionalElderVisit.get();
        if(inputVO.getStatus().equals(ElderVisitStatusEnum.CANCEL.getValue())){
            if(!optionalElderVisit.get().status().equals(ElderVisitStatusEnum.RESERVED.getValue())){
                throw exception(ELDER_VISIT_RESERVED_CAN_CANCEL);
            }
            // 取消来访登记
            elderVisit = ElderVisitDraft.$.produce(elderVisit, draft -> {
                draft.setStatus(inputVO.getStatus());
            });

        } else if(inputVO.getStatus().equals(ElderVisitStatusEnum.VISITED.getValue())){
            if(!optionalElderVisit.get().status().equals(ElderVisitStatusEnum.RESERVED.getValue())){
                throw exception(ELDER_VISIT_RESERVED_CAN_VISIT);
            }
            // 确认来访登记
            elderVisit = ElderVisitDraft.$.produce(elderVisit, draft -> {
                draft.setStatus(inputVO.getStatus()).setVisitTime(inputVO.getTime());
            });
        } else if(inputVO.getStatus().equals(ElderVisitStatusEnum.LEAVE.getValue())){
            if(!optionalElderVisit.get().status().equals(ElderVisitStatusEnum.VISITED.getValue())){
                throw exception(ELDER_VISIT_VISIT_CAN_LEAVE);
            }
            // 确认离开
            elderVisit = ElderVisitDraft.$.produce(elderVisit, draft -> {
                draft.setStatus(inputVO.getStatus()).setLeaveTime(inputVO.getTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            });
        } else {
            throw exception(ELDER_VISIT_UPDATE_STATUS_ERROR);
        }
        elderVisitRepository.update(elderVisit);
        return true;
    }

    @Override
    public VisitSingleGetOutput singleGet(Long id) {
        Optional<ElderVisit> optionElderVisit = elderVisitRepository.findDetailById(id);
        if(!optionElderVisit.isPresent()){
            throw exception(ELDER_VISIT_NOT_EXIST);
        }
        return VisitConvert.INSTANCE.singleGetOutputConvert(optionElderVisit.get());

    }

}
